home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / HexEdit 1.21 / ~Project / Source / EditWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-03  |  51.0 KB  |  1,931 lines  |  [TEXT/CWIE]

  1. /*********************************************************************
  2.  * EditWindow.c
  3.  *
  4.  * HexEdit, a simple hex editor
  5.  * copyright 1993, Jim Bumgardner
  6.  *
  7.  * Modifications by Lane Roathe, Ideas From the Deep, marked "//LR"
  8.  *********************************************************************/
  9. #include "HexEdit.h"
  10. #include "Folders.h"
  11. #include <stdio.h>
  12.  
  13. #define OK 1
  14. #define Cancel 2
  15.  
  16. // Create a new main window using a 'WIND' template from the resource fork
  17. //
  18.  
  19. Boolean         gCursorFlag;
  20. Rect            gCursRect;
  21. Preferences        gPrefs = {AM_Lo, false, true};
  22. short            gForkMode=FM_Smart,gHighChar='~',gOverwrite;
  23. THPrint            gHPrint;
  24. static char        gBuffer[80];
  25. Cursor            gWatchCursor,gIBeamCursor;
  26. short            gMaxHeight=342,CompareFlag;
  27. WindowPtr        CompWind1,CompWind2;
  28.  
  29. DlgHookUPP myGetFileUPP;    //LR :new method
  30.  
  31. static void LoadPreferences(void)
  32. {
  33.     Handle    h;
  34.     h = GetResource(PrefResType, PrefResID);
  35.     if (h == NULL || ResError())
  36.         return;
  37.     BlockMove(*h, &gPrefs, sizeof(Preferences));
  38.     ReleaseResource(h);
  39.     if (gPrefs.asciiMode)
  40.         gHighChar = 255;
  41.     else
  42.         gHighChar = '~';
  43. }
  44.  
  45. static void SavePreferences(void)
  46. {
  47.     Handle    h;
  48.     while ((h = GetResource(PrefResType, PrefResID)) != NULL) {
  49.         RemoveResource(h);
  50.         DisposeHandle(h);
  51.     }
  52.     h = NewHandle(sizeof(Preferences));
  53.     if (h == NULL) {
  54.         ErrorAlert(ES_Caution,"Not enough memory");
  55.     }
  56.     else {
  57.         BlockMove(&gPrefs, *h, sizeof(Preferences));
  58.         AddResource(h,PrefResType,PrefResID,"\pPreferences");
  59.         WriteResource(h);
  60.         ReleaseResource(h);
  61.     }
  62. }
  63.  
  64. void InitializeEditor(void)
  65. {
  66.     CursHandle            cH = NULL;
  67.     PScrapStuff            ScrapInfo;    //LR :see below
  68.  
  69. //    if (ScrapInfo.scrapState < 0)
  70.     ScrapInfo = InfoScrap();                //LR :correct compile error
  71.     if (ScrapInfo->scrapState < 0)
  72.         ZeroScrap();
  73.  
  74.     // Start Profiling
  75. #if PROFILE            // 6/15 Optional profiling support
  76.     freopen("profile.log","w",stdout);        // If console isn't wanted
  77.     InitProfile(200,200);
  78.     _profile = 0;
  79.     // cecho2file("profile.log",false,stdout);    // If console is wanted
  80. #endif
  81.     gMaxHeight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;    //LR :add 'qd.'
  82.     if (gMaxHeight < 342)
  83.         gMaxHeight = 342;
  84.  
  85.     cH = GetCursor(watchCursor);
  86.     if (cH)
  87.         gWatchCursor = **cH;
  88.     cH = GetCursor(iBeamCursor);
  89.     if (cH)
  90.         gIBeamCursor = **cH;
  91.  
  92.     PrOpen();
  93.     gHPrint = (THPrint) NewHandle(sizeof(TPrint));
  94.     if (gHPrint == NULL) {
  95.         ErrorAlert(ES_Stop,"Not enough memory");
  96.     }
  97.     PrintDefault(gHPrint);
  98.     PrClose();
  99.  
  100.     LoadPreferences();
  101. }
  102.  
  103. void CleanupEditor(void)
  104. {
  105.     SavePreferences();
  106. }
  107.  
  108. void NewEditWindow(void)
  109. {
  110.     WindowPtr            theWindow;
  111.     EditWindowPtr        dWin;
  112.     OSErr                oe;
  113.     short                refNum=0;
  114.     Point                where={-1,-1};
  115.     FSSpec                workSpec;
  116.     Rect                r,offRect;
  117.  
  118.     // Get the Template & Create the Window, it is set up in the resource fork
  119.     // to not be initially visible 
  120.  
  121.     dWin = (EditWindowPtr) NewPtrClear(sizeof(EditWindowRecord));
  122.     if (dWin == NULL) {
  123.         FSClose(refNum);
  124.         ErrorAlert(ES_Caution, "Can't allocate new window");
  125.         return;
  126.     }
  127.  
  128.     dWin->fork = FT_Data;
  129.     dWin->fileSize = 0L;
  130.     dWin->refNum = 0;
  131.  
  132.     // Initialize WorkSpec
  133.     workSpec = dWin->workSpec;
  134.     oe = FindFolder(-1, kTemporaryFolderType, kCreateFolder, 
  135.                     &workSpec.vRefNum,
  136.                     &workSpec.parID);
  137.     if (oe != noErr) {
  138.         OSErrorAlert(ES_Caution, "FindFolder", oe);
  139.         return;
  140.     }
  141.     BlockMove("\pUntitledw", workSpec.name, 10);
  142.     InsureNameIsUnique(&workSpec);
  143.     HCreate(workSpec.vRefNum,workSpec.parID,workSpec.name,CREATOR, '????');
  144.     if (oe != noErr) {
  145.         OSErrorAlert(ES_Caution, "HCreate", oe);
  146.         return;
  147.     }
  148.     oe = HOpen(workSpec.vRefNum,workSpec.parID,workSpec.name,fsRdWrPerm,&refNum);
  149.     if (oe != noErr) {
  150.         OSErrorAlert(ES_Caution, "HOpen", oe);
  151.         return;
  152.     }
  153.  
  154.     dWin->workSpec = workSpec;
  155.     dWin->workRefNum = refNum;
  156.     dWin->workBytesWritten = 0L;
  157.  
  158.     dWin->fileType = DEFFILETYPE;
  159.     dWin->creator = CREATOR;
  160.     dWin->creationDate = 0L;
  161.  
  162.     theWindow = InitObjectWindow(MainWIND, (ObjectWindowPtr) dWin,false);
  163.     if (theWindow == NULL)
  164.         ErrorAlert(ES_Stop,"Not enough memory");
  165.  
  166.     SizeWindow(theWindow,484+SBarSize-1-1,gMaxHeight-64,true);
  167.     SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight - 44);
  168.     OffsetRect(&r,3,41);
  169.     ((WStateData *)*((WindowPeek) theWindow)->dataHandle)->stdState = r;
  170.  
  171.     SetWTitle(theWindow, "\pUntitled");
  172.  
  173.     ((ObjectWindowPtr) theWindow)->Draw = MyDraw;
  174.     ((ObjectWindowPtr) theWindow)->Idle = MyIdle;
  175.     ((ObjectWindowPtr) theWindow)->HandleClick = MyHandleClick;
  176.     ((ObjectWindowPtr) theWindow)->Dispose = DisposeEditWindow;
  177.     ((ObjectWindowPtr) theWindow)->ProcessKey = MyProcessKey;
  178.     ((ObjectWindowPtr) theWindow)->Save = SaveContents;
  179.     ((ObjectWindowPtr) theWindow)->SaveAs = SaveAsContents;
  180.     ((ObjectWindowPtr) theWindow)->Revert = RevertContents;
  181.     ((ObjectWindowPtr) theWindow)->Activate = MyActivate;
  182.  
  183.     SetRect(&offRect,0,0,MaxWindowWidth,gMaxHeight);
  184.  
  185.     dWin->bitMap.rowBytes = (((MaxWindowWidth-1)/32)+1)*4;
  186.     dWin->bitMap.baseAddr = NewPtrClear( (long) dWin->bitMap.rowBytes * gMaxHeight );
  187.     if (dWin->bitMap.baseAddr == NULL)
  188.         ErrorAlert(ES_Stop,"Not enough memory");
  189.     dWin->bitMap.bounds = offRect;
  190.     
  191.     // Show the window
  192.     ShowWindow(theWindow);
  193.  
  194.     // Make it the current grafport
  195.     SetPort(theWindow);
  196.  
  197.     
  198.     dWin->linesPerPage = ((theWindow->portRect.bottom - SBarSize) - TopMargin - BotMargin - HeaderHeight)/LineHeight;
  199.     dWin->startSel = dWin->endSel = 0L;
  200.     dWin->editMode = EM_Hex;
  201.  
  202.     SetupScrollBars(dWin);
  203.  
  204.     dWin->firstChunk = NewChunk(0L,0L,0L, CT_Unwritten);
  205.     dWin->curChunk = dWin->firstChunk;
  206. }
  207.  
  208. #define DataItem        11
  209. #define RsrcItem        12
  210. #define SmartItem        13
  211.  
  212. /*SFReply        *gReplyPtr;*/
  213.  
  214. pascal int SourceDLOGHook(short item, DialogPtr theDialog)
  215. {
  216.     switch (item) {
  217.     case DataItem:
  218.     case RsrcItem:
  219.     case SmartItem:
  220.         SetControl(theDialog,gForkMode+DataItem,false);
  221.         gForkMode = item - DataItem;
  222.         SetControl(theDialog,gForkMode+DataItem,true);
  223.         return sfHookNullEvent;    /* Redraw the List */
  224.     case sfHookFirstCall:
  225.         SetControl(theDialog,gForkMode+DataItem,true);
  226.         return sfHookNullEvent;
  227.     }
  228.     return item;
  229. }
  230.  
  231. int AskEditWindow(void)
  232. {
  233.     SFReply            macSFReply;
  234.     FSSpec            fSpec;
  235.     long                procID;
  236.     Point                where = {-1,-1};
  237.  
  238.     // StandardGetFile(NULL, -1, NULL, &reply);
  239.     if (!gSys7Flag) {
  240.         where.h = 20;
  241.         where.v = 90;
  242.     }
  243.  
  244.     //LR :hacks for requesting different files for comparing…
  245.  
  246.     if( CompareFlag==1 )
  247.     {
  248.         SFPGetFile(where, "\pFirst File to Compare:", NULL, -1, NULL, myGetFileUPP, 
  249.                 &macSFReply, GetFileDLOG, NULL);
  250.     }
  251.     else if( CompareFlag==2 )
  252.     {
  253.         SFPGetFile(where, "\pSecond File to Compare:", NULL, -1, NULL, myGetFileUPP, 
  254.                 &macSFReply, GetFileDLOG, NULL);
  255.     }
  256.     else
  257.     {
  258.         SFPGetFile(where, "\pFile to Open:", NULL, -1, NULL, myGetFileUPP, 
  259.                 &macSFReply, GetFileDLOG, NULL);
  260.     }
  261.  
  262.     if (macSFReply.good)
  263.     {
  264.         BlockMove(macSFReply.fName,fSpec.name,macSFReply.fName[0]+1);
  265.         GetWDInfo(macSFReply.vRefNum, &fSpec.vRefNum, &fSpec.parID, &procID);
  266.         OpenEditWindow(&fSpec);
  267.     }
  268.     else
  269.         return( -1 );
  270.  
  271.     MyAdjustMenus();
  272.     return( 0 );
  273. }
  274.  
  275.  
  276.  
  277.  
  278. void OpenEditWindow(FSSpec *fsSpec)
  279. {
  280.     WindowPtr            theWindow;
  281.     EditWindowPtr        dWin;
  282.     OSErr                oe;
  283.     short                refNum=0;
  284.     Point                where={-1,-1};
  285.     HParamBlockRec        pb;
  286.     FSSpec                workSpec;
  287.     Rect                r,offRect;
  288.  
  289.     // Get the Template & Create the Window, it is set up in the resource fork
  290.     // to not be initially visible 
  291.  
  292.  
  293.     pb.fileParam.ioCompletion = 0l;
  294.     pb.fileParam.ioNamePtr = fsSpec->name;
  295.     pb.fileParam.ioVRefNum = fsSpec->vRefNum;
  296.     pb.fileParam.ioDirID = fsSpec->parID;
  297.     pb.fileParam.ioFDirIndex = 0;
  298.  
  299.     if ((oe = PBHGetFInfoSync(&pb)) != noErr) {
  300.         OSErrorAlert(ES_Caution, "PBHGetFInfo", oe);
  301.         return;
  302.     }
  303.  
  304.     // fileSize = pb.fileParam.ioFlLgLen;    // Data Fork Length!!!!
  305.     // GetEOF(refNum,&fileSize);
  306.  
  307.     dWin = (EditWindowPtr) NewPtrClear(sizeof(EditWindowRecord));
  308.     if (dWin == NULL) {
  309.         FSClose(refNum);
  310.         ErrorAlert(ES_Caution, "Can't allocate new window");
  311.         return;
  312.     }
  313.  
  314.     if (gForkMode == FM_Data || (pb.fileParam.ioFlLgLen > 0 && gForkMode == FM_Smart)) {
  315.         // Open Data Fork
  316.         dWin->fork = FT_Data;
  317.         oe = HOpen(fsSpec->vRefNum,fsSpec->parID,fsSpec->name,fsRdPerm,&refNum);
  318.         if (oe == fnfErr) {
  319.             ParamText(fsSpec->name,"\pdata","\p","\p");
  320.             if (CautionAlert(NoForkALRT,NULL) != 2)
  321.                 return;
  322.             oe = HCreate(fsSpec->vRefNum,fsSpec->parID,fsSpec->name,
  323.                         pb.fileParam.ioFlFndrInfo.fdCreator,
  324.                         pb.fileParam.ioFlFndrInfo.fdType);
  325.             if (oe != noErr) {
  326.                 OSErrorAlert(ES_Caution, "HCreate", oe);
  327.                 return;
  328.             }
  329.             oe = HOpen(fsSpec->vRefNum,fsSpec->parID,fsSpec->name,fsRdPerm,&refNum);
  330.         }
  331.         if (oe != noErr) {
  332.             OSErrorAlert(ES_Caution, "HOpen", oe);
  333.             return;
  334.         }
  335.         dWin->fileSize = pb.fileParam.ioFlLgLen;
  336.     }
  337.     else {
  338.         // Open Resource Fork
  339.         dWin->fork = FT_Resource;
  340.         oe = HOpenRF(fsSpec->vRefNum,fsSpec->parID,fsSpec->name,fsRdPerm,&refNum);
  341.         if (oe == fnfErr) {
  342.             ParamText(fsSpec->name,"\presource","\p","\p");
  343.             if (CautionAlert(NoForkALRT,NULL) != 2)
  344.                 return;
  345.             HCreateResFile(fsSpec->vRefNum,fsSpec->parID,fsSpec->name);
  346.             if ((oe = ResError()) != noErr) {
  347.                 OSErrorAlert(ES_Caution, "HCreateResFile", oe);
  348.                 return;
  349.             }
  350.             oe = HOpenRF(fsSpec->vRefNum,fsSpec->parID,fsSpec->name,fsRdPerm,&refNum);
  351.         }
  352.         if (oe != noErr) {
  353.             OSErrorAlert(ES_Caution, "HOpenRF", oe);
  354.             return;
  355.         }
  356.         dWin->fileSize = pb.fileParam.ioFlRLgLen;
  357.     }
  358.  
  359.     dWin->refNum = refNum;
  360.  
  361.     workSpec = *fsSpec;
  362.     oe = FindFolder(-1, kTemporaryFolderType, kCreateFolder, 
  363.                     &workSpec.vRefNum,
  364.                     &workSpec.parID);
  365.     if (oe != noErr) {
  366.         OSErrorAlert(ES_Caution, "FindFolder", oe);
  367.         return;
  368.     }
  369.     if (workSpec.name[0] < 31) {
  370.         workSpec.name[0]++;
  371.         workSpec.name[workSpec.name[0]] = 'w';
  372.     }
  373.     else
  374.         workSpec.name[31] ^= 0x10;
  375.     InsureNameIsUnique(&workSpec);
  376.     oe = HCreate(workSpec.vRefNum,workSpec.parID,workSpec.name,CREATOR, '????');
  377.     if (oe != noErr) {
  378.         OSErrorAlert(ES_Caution, "HCreate", oe);
  379.         return;
  380.     }
  381.     oe = HOpen(workSpec.vRefNum,workSpec.parID,workSpec.name,fsRdWrPerm,&refNum);
  382.     if (oe != noErr) {
  383.         OSErrorAlert(ES_Caution, "HOpen", oe);
  384.         return;
  385.     }
  386.  
  387.     dWin->workSpec = workSpec;
  388.     dWin->workRefNum = refNum;
  389.     dWin->workBytesWritten = 0L;
  390.  
  391.     dWin->fileType = pb.fileParam.ioFlFndrInfo.fdType;
  392.     dWin->creator = pb.fileParam.ioFlFndrInfo.fdCreator;
  393.     dWin->creationDate =  pb.fileParam.ioFlCrDat;
  394.  
  395.     theWindow = InitObjectWindow(MainWIND, (ObjectWindowPtr) dWin,false);
  396. //LR    SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight - 64);
  397.  
  398.     //LR : Hack for comparing two files
  399.     if(CompareFlag == 0)
  400.     {
  401.         SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight - 64);
  402.     }
  403.     if(CompareFlag == 1)
  404.     {
  405.         SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight/2 - 64);
  406.         CompWind1 = theWindow;
  407.     }
  408.     if(CompareFlag == 2)
  409.     {
  410.         SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight/2 - 64);
  411.         MoveWindow(theWindow,14,gMaxHeight/2,true);
  412.         CompWind2 = theWindow;
  413.     }
  414.  
  415.     dWin->linesPerPage = ((r.bottom - SBarSize) - TopMargin - BotMargin - HeaderHeight)/LineHeight;
  416.  
  417.     if ((dWin->linesPerPage-1) * 16L > dWin->fileSize)
  418.         r.bottom -= LineHeight * (((dWin->linesPerPage-1) * 16L) - dWin->fileSize)/16;
  419.     if (r.bottom < SBarSize+TopMargin+BotMargin+HeaderHeight+LineHeight*3)
  420.         r.bottom = SBarSize+TopMargin+BotMargin+HeaderHeight+LineHeight*3;
  421.  
  422.     SizeWindow(theWindow,r.right-1,r.bottom,true);
  423.     SetRect(&r, 0, 0, MaxWindowWidth+SBarSize-1, gMaxHeight - 44);
  424.     OffsetRect(&r,3,41);
  425.     ((WStateData *) *((WindowPeek) theWindow)->dataHandle)->stdState = r;
  426.     SetWTitle(theWindow, fsSpec->name);
  427.     dWin->fsSpec = *fsSpec;
  428.     dWin->destSpec = dWin->fsSpec;
  429.  
  430.     ((ObjectWindowPtr) theWindow)->Draw = MyDraw;
  431.     ((ObjectWindowPtr) theWindow)->Idle = MyIdle;
  432.     ((ObjectWindowPtr) theWindow)->HandleClick = MyHandleClick;
  433.     ((ObjectWindowPtr) theWindow)->Dispose = DisposeEditWindow;
  434.     ((ObjectWindowPtr) theWindow)->ProcessKey = MyProcessKey;
  435.     ((ObjectWindowPtr) theWindow)->Save = SaveContents;
  436.     ((ObjectWindowPtr) theWindow)->SaveAs = SaveAsContents;
  437.     ((ObjectWindowPtr) theWindow)->Revert = RevertContents;
  438.     ((ObjectWindowPtr) theWindow)->Activate = MyActivate;
  439.     
  440.     SetRect(&offRect,0,0,MaxWindowWidth,gMaxHeight);
  441.  
  442.     dWin->bitMap.rowBytes = (((MaxWindowWidth-1)/32)+1)*4;
  443.     dWin->bitMap.baseAddr = NewPtrClear( (long) dWin->bitMap.rowBytes * gMaxHeight );
  444.     if (dWin->bitMap.baseAddr == NULL)
  445.         ErrorAlert(ES_Stop,"Not enough memory");
  446.     dWin->bitMap.bounds = offRect;
  447.  
  448.  
  449.     // Show the window
  450.     ShowWindow(theWindow);
  451.  
  452.     // Make it the current grafport
  453.     SetPort(theWindow);
  454.     
  455.     dWin->linesPerPage = ((theWindow->portRect.bottom - SBarSize) - TopMargin - BotMargin - HeaderHeight)/LineHeight;
  456.     dWin->startSel = dWin->endSel = 0L;
  457.     dWin->editMode = EM_Hex;
  458.  
  459.     SetupScrollBars(dWin);
  460.  
  461.     LoadFile(dWin);
  462. }
  463.  
  464. void DisposeEditWindow(WindowPtr theWindow)
  465. {
  466.     EditWindowPtr    dWin = (EditWindowPtr) theWindow;
  467.  
  468.     UnloadFile(dWin);
  469.     if (dWin->refNum)
  470.         FSClose(dWin->refNum);
  471.     if (dWin->workRefNum) {
  472.         FSClose(dWin->workRefNum);
  473.         HDelete(dWin->workSpec.vRefNum, dWin->workSpec.parID, dWin->workSpec.name);
  474.     }
  475.     if (dWin->bitMap.baseAddr) {
  476.         DisposePtr(dWin->bitMap.baseAddr);
  477.     }
  478.     DefaultDispose(theWindow);
  479.     MyAdjustMenus();
  480. }
  481.  
  482. Boolean    CloseEditWindow(WindowPtr theWindow)
  483. {
  484.     Str63            fileName;
  485.     EditWindowPtr    dWin = (EditWindowPtr) theWindow;
  486.  
  487.     MySetCursor(C_Arrow);
  488.  
  489.     if (dWin->dirtyFlag) {
  490.         GetWTitle(theWindow, fileName);
  491.         ParamText(fileName, "\p","\p","\p");
  492.         switch (NoteAlert(SaveChangesALRT, NULL))
  493.         {
  494.         case OK:
  495.             SaveContents(theWindow);    
  496.             break;
  497.         case Cancel:
  498.             return false;
  499.         case 3:
  500.             // Discard
  501.             break;
  502.         }
  503.     }
  504.     ((ObjectWindowPtr) dWin)->Dispose(theWindow);
  505.     return true;
  506. }
  507.  
  508. Boolean CloseAllEditWindows(void)
  509. {
  510.     WindowPeek    wp;
  511.     wp = (WindowPeek) FrontWindow();
  512.     while (wp) {
  513.         if (wp->windowKind < 0)
  514.              CloseDeskAcc(wp->windowKind);
  515.         else if (wp->refCon == MyWindowID) {
  516.             if (!CloseEditWindow((WindowPtr) wp))
  517.                 return false;
  518.         }
  519.         else if ((WindowPtr) wp == gSearchWin) {
  520.             DisposeDialog(gSearchWin);
  521.             gSearchWin = NULL;
  522.         }
  523.         else
  524.             return false;
  525.         wp = (WindowPeek) FrontWindow();
  526.     }
  527.     return true;
  528. }
  529.  
  530. // Locate Edit Window    (LR 951121)
  531. //
  532. // ENTRY:    File's refnum of Edit window to find, and fork open
  533. //  EXIT:    ptr to edit window, or NULL if not found
  534.  
  535. EditWindowPtr LocateEditWindow( FSSpec *fs, short fork )
  536. {
  537.     EditWindowPtr    wp;
  538.  
  539.     wp = (EditWindowPtr) FrontWindow();
  540.  
  541.     while( wp )
  542.     {
  543.         if( ((WindowPeek)wp)->refCon == MyWindowID && wp->fork == fork )    // simple checks
  544.         {
  545.             if( EqualString( fs->name, wp->fsSpec.name, false, true ) &&
  546.                     fs->vRefNum == wp->fsSpec.vRefNum && fs->parID == wp->fsSpec.parID )    // tedious, but only way…
  547.                 return( (EditWindowPtr)wp );
  548.         }
  549.  
  550.         wp = (EditWindowPtr)((WindowPeek)wp)->nextWindow;    // to next!
  551.     }
  552.     return( NULL );
  553. }
  554.  
  555. // Respond to an update event - BeginUpdate has already been called.
  556. //
  557.  
  558. void MyDraw(WindowPtr theWindow)
  559. {
  560.     RgnHandle        rg1,rg2,rg3;
  561.     Rect            r3;
  562.     EditWindowPtr    dWin = (EditWindowPtr) theWindow;
  563.  
  564.     rg1 = NewRgn();
  565.     rg2 = NewRgn();
  566.     rg3 = NewRgn();
  567.     RectRgn(rg1, &theWindow->portRect);
  568.     RectRgn(rg2, &dWin->bitMap.bounds);
  569.     r3 = theWindow->portRect;
  570.     r3.right -= SBarSize-1;
  571.     r3.bottom -= SBarSize-1;
  572.     RectRgn(rg3, &r3);
  573.     SectRgn(rg2,rg3,rg2);    // Intersection of offscreen and valid content area
  574.     DiffRgn(rg1,rg2,rg1);    // Subtract from whole content area
  575.     EraseRgn(rg1);
  576.     DisposeRgn(rg1);
  577.     DisposeRgn(rg2);
  578.     DisposeRgn(rg3);
  579.     // Draw the grow icon in the corner
  580.     // EraseRect(&theWindow->portRect);
  581.     DrawControls(theWindow);
  582.     DrawGrowIcon(theWindow);
  583.     DrawPage((EditWindowPtr) theWindow);
  584.     UpdateOnscreen(theWindow);
  585. }
  586.  
  587. void UpdateOnscreen(WindowPtr theWindow)
  588. {
  589.     Rect            r1,r2,r3;
  590.     EditWindowPtr    dWin = (EditWindowPtr) theWindow;
  591.  
  592.     gCursorFlag = false;
  593.     r1 = dWin->bitMap.bounds;
  594.     r2 = theWindow->portRect;
  595.     r2.right -= SBarSize - 1;
  596.     r2.bottom -= SBarSize - 1;
  597.     SectRect(&r1,&r2,&r3);
  598.     SetPort(theWindow);
  599.     CopyBits(&dWin->bitMap,&theWindow->portBits,&r3,&r3,srcCopy,0L);
  600.     if (dWin->endSel > dWin->startSel && 
  601.         dWin->endSel >= dWin->editOffset &&
  602.         dWin->startSel < dWin->editOffset+(dWin->linesPerPage<<4)) 
  603.         InvertSelection(dWin);
  604. }
  605.  
  606. void MyIdle(WindowPtr theWin, EventRecord *er)
  607. {
  608.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  609.     Boolean            frontWindowFlag;
  610.     Point            w;
  611.     PScrapStuff     ScrapInfo;    //LR :see below
  612.  
  613.     frontWindowFlag = (theWin == FrontWindow() &&
  614.                         dWin->oWin.active);
  615.     if (frontWindowFlag) {
  616.         w = er->where;
  617.         SetPort(theWin);
  618.         GlobalToLocal(&w);
  619.         if (w.v >= HeaderHeight+TopMargin && 
  620.             w.v < HeaderHeight+TopMargin+(dWin->linesPerPage*LineHeight))
  621.         {
  622.                 if (w.h >= AddrPos+CharPos(HexStart) &&
  623.                     w.h < AddrPos+CharPos(HexStart)+(HexWidth<<4)) 
  624.                     MySetCursor(C_IBeam);
  625.                 else if (w.h >= AddrPos+CharPos(AsciiStart) &&
  626.                          w.h < AddrPos+CharPos(AsciiStart)+(CharWidth<<4))
  627.                     MySetCursor(C_IBeam);
  628.                 else
  629.                     MySetCursor(C_Arrow);
  630.         }
  631.         else
  632.             MySetCursor(C_Arrow);
  633.  
  634.         if (dWin->startSel == dWin->endSel) {
  635. //LR            if ((Ticks & 0x1F) < 0x10)
  636.         if( (TickCount() & 0x1F) < 0x10)
  637.                 CursorOn(theWin);
  638.             else
  639.                 CursorOff(theWin);
  640.         }
  641. //LR        if (gScrapCount != ScrapInfo.scrapCount) {
  642.         ScrapInfo = InfoScrap();
  643.         if (gScrapCount != ScrapInfo->scrapCount)    //LR :correct way to do it
  644.         {
  645.             EditChunk    **nc;
  646. //LR            Handle        h;
  647.             long        size,offset;
  648.             size = GetScrap(NULL, 'TEXT', &offset);
  649.             if (size > 0) {
  650.                 nc = NewChunk(size,0,0,CT_Unwritten);
  651.                 if (nc == NULL)
  652.                     ErrorAlert(ES_Caution,"Not enough memory for desktop scrap");
  653.                 else {
  654.                     ReleaseEditScrap(dWin, &gScrapChunk);
  655.                     gScrapChunk = nc;
  656.                     GetScrap((*gScrapChunk)->data,'TEXT',&offset);
  657.                     (*gScrapChunk)->lastCtr = 1;    // Flag as external
  658.                 }
  659.             }
  660.             gScrapCount = ScrapInfo->scrapCount;
  661.         }
  662.     }
  663. }
  664.  
  665.  
  666. // Respond to a mouse-click - highlight cells until the user releases the button
  667. //
  668. void MyHandleClick(WindowPtr theWin, Point where, EventRecord *er)
  669. {
  670.     Point    w;
  671.     long    pos;
  672.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  673.     long    anchorPos = -1,sPos,ePos;
  674.  
  675.     SetPort(theWin);
  676.     w = where;
  677.     GlobalToLocal(&w);
  678.     if (HandleControlClick(theWin,w))
  679.         return;
  680.     // Else handle editing chore
  681.     CursorOff(theWin);
  682.     if (w.v >= HeaderHeight+TopMargin && 
  683.         w.v < HeaderHeight+TopMargin+(dWin->linesPerPage*LineHeight))
  684.     {
  685.         do {
  686.             AutoScroll(dWin, w);
  687.  
  688.             if (w.h >= AddrPos+CharPos(HexStart) &&
  689.                 w.h < AddrPos+CharPos(HexStart)+(HexWidth<<4)) 
  690.             {
  691.  
  692.                 pos = ((w.v - (HeaderHeight+TopMargin))/LineHeight)*16 +
  693.                       (w.h - (AddrPos+CharPos(HexStart))+12) / HexWidth;
  694.                 dWin->editMode = EM_Hex;
  695.             }
  696.             else if (w.h >= AddrPos+CharPos(AsciiStart) &&
  697.                      w.h < AddrPos+CharPos(AsciiStart)+(CharWidth<<4))
  698.             {
  699.                 pos = ((w.v - (HeaderHeight+TopMargin))/LineHeight)*16 +
  700.                       (w.h - (AddrPos+CharPos(AsciiStart))+3) / CharWidth;
  701.                 dWin->editMode = EM_Ascii;
  702.             }
  703.             else {
  704.                 goto GetMouseLabel;
  705.             }
  706.             pos += dWin->editOffset;
  707.             if (pos < dWin->editOffset)
  708.                 pos = dWin->editOffset;
  709.             if (pos > dWin->editOffset+(dWin->linesPerPage<<4))
  710.                 pos = dWin->editOffset+(dWin->linesPerPage<<4);
  711.             if (pos > dWin->fileSize)
  712.                 pos = dWin->fileSize;
  713.             if (anchorPos == -1) {
  714.                 if (er->modifiers & shiftKey)
  715.                     anchorPos = (pos < dWin->startSel)? dWin->endSel : dWin->startSel;
  716.                 else
  717.                     anchorPos = pos;
  718.             }
  719.             sPos = pos < anchorPos? pos : anchorPos;
  720.             ePos = pos > anchorPos? pos : anchorPos;
  721.             if (ePos > dWin->fileSize)
  722.                 ePos = dWin->fileSize;
  723.  
  724.             if (sPos != dWin->startSel ||
  725.                 ePos != dWin->endSel) {
  726.                 dWin->startSel = sPos;
  727.                 dWin->endSel = ePos;
  728.                 UpdateOnscreen(theWin);
  729.             }
  730.  
  731.     GetMouseLabel:
  732.             GetMouse(&w);
  733.         } while (WaitMouseUp());
  734.     }
  735. }
  736.  
  737. static void DrawHeader(EditWindowPtr dWin, Rect *r)
  738. {
  739.     TextFont(monaco);
  740.     TextSize(9);
  741.     TextFace(bold);
  742.     TextMode(srcCopy);
  743.  
  744.     MoveTo(r->left,r->top+HeaderHeight-1);
  745.     LineTo(r->right,r->top+HeaderHeight-1);
  746.  
  747.     MoveTo(20, r->top+HeaderHeight-DescendHeight-2);
  748.     if (gPrefs.decimalAddr)
  749.         sprintf(gBuffer,"Length: %7ld    Type: %4.4s    Creator: %4.4s    Fork: %s", 
  750.             dWin->fileSize,&dWin->fileType, &dWin->creator,
  751.             ((dWin->fork == FT_Data)? "data" : "rsrc"));
  752.     else
  753.         sprintf(gBuffer,"Length: %6lXh    Type: %4.4s    Creator: %4.4s    Fork: %s", 
  754.             dWin->fileSize,&dWin->fileType, &dWin->creator,
  755.             ((dWin->fork == FT_Data)? "data" : "rsrc"));
  756.     DrawText(gBuffer,0,strlen(gBuffer));
  757. }
  758.  
  759. static void DrawFooter(EditWindowPtr dWin, Rect *r, short pageNbr, short nbrPages)
  760. {
  761.     unsigned long    tim;
  762.     DateTimeRec        dat;
  763.     Str31            fileName;
  764.  
  765.     TextFont(monaco);
  766.     TextSize(9);
  767.     TextFace(0);
  768.     TextMode(srcCopy);
  769.  
  770.     GetDateTime(&tim);
  771.     SecondsToDate(tim,&dat);
  772.  
  773.     MoveTo(r->left,r->top);
  774.     LineTo(r->right,r->top);
  775.  
  776.     sprintf(gBuffer, "%02d/%02d/%02d %02d:%02d",
  777.         dat.month,dat.day,dat.year-1900,dat.hour,dat.minute);
  778.  
  779.     MoveTo(20, r->top+FooterHeight-DescendHeight-2);
  780.     DrawText(gBuffer,0,strlen(gBuffer));
  781.  
  782.     GetWTitle((WindowPtr) dWin, fileName);
  783.     sprintf(gBuffer,"File: %.*s", fileName[0],&fileName[1]);
  784.     MoveTo((r->left+r->right)/2 - TextWidth(gBuffer,0,strlen(gBuffer))/2,
  785.              r->top+FooterHeight-DescendHeight-2);
  786.     DrawText(gBuffer,0,strlen(gBuffer));
  787.     
  788.     sprintf(gBuffer,"%d of %d",pageNbr,nbrPages);
  789.     MoveTo(r->right - TextWidth(gBuffer,0,strlen(gBuffer)) - 8, 
  790.             r->top+FooterHeight-DescendHeight-2);
  791.     DrawText(gBuffer,0,strlen(gBuffer));
  792. }
  793.  
  794. static void DrawDump(EditWindowPtr dWin, Rect *r, long sAddr, long eAddr)
  795. {
  796.     short    y;
  797.     short    hexPos;
  798.     short    asciiPos;
  799.     register short    i,ch,ch1,ch2;
  800.     long    addr;
  801.     TextFont(monaco);
  802.     TextSize(9);
  803.     TextFace(0);
  804.     TextMode(srcCopy);
  805.  
  806.     addr = sAddr - (sAddr % 16);
  807.     for (y = r->top; y < r->bottom && addr < eAddr; y += LineHeight) {
  808.         MoveTo(AddrPos,y);
  809.         if (gPrefs.decimalAddr)
  810.             sprintf(gBuffer,"%7ld: ", addr);
  811.         else
  812.             sprintf(gBuffer,"%06lX:  ", addr);
  813.         hexPos = HexStart;
  814.         asciiPos = AsciiStart;
  815.         for (i = 16; i; --i,++addr) {
  816.             if (addr >= sAddr && addr < eAddr) {
  817.                 ch = GetByte(dWin, addr);
  818.                 ch1 = ch2 = ch;
  819.                 ch1 >>= 4;
  820.                 ch2 &= 0x0F;
  821.                 gBuffer[hexPos++] = ch1 + ((ch1 < 10)? '0' : ('A'-10));
  822.                 gBuffer[hexPos++] = ch2 + ((ch2 < 10)? '0' : ('A'-10));
  823.                 gBuffer[hexPos++] = ' ';
  824.                 gBuffer[asciiPos++] = ((ch >= ' ' && ch <= gHighChar)? ch : '.');
  825.             }
  826.             else {
  827.                 gBuffer[hexPos++] = ' ';
  828.                 gBuffer[hexPos++] = ' ';
  829.                 gBuffer[hexPos++] = ' ';
  830.                 gBuffer[asciiPos++] = ' ';
  831.             }
  832.         }
  833.         gBuffer[57] = ' ';
  834.         gBuffer[58] = ' ';
  835.         MoveTo(AddrPos,y);
  836.         DrawText(gBuffer,0,75);
  837.     }
  838. }
  839.  
  840. void DrawPage(EditWindowPtr dWin)
  841. {
  842.     GrafPtr            savePort;
  843.     Rect            r;
  844.     BitMap            realBits;
  845.  
  846. #if PROFILE
  847.     _profile = 1;
  848. #endif
  849.     GetPort(&savePort);
  850.     SetPort((GrafPtr) dWin);
  851.  
  852.     realBits = ((GrafPtr) dWin)->portBits;
  853.     SetPortBits(&dWin->bitMap);
  854.  
  855.     r = ((WindowPtr) dWin)->portRect;
  856.     r.right -= (SBarSize - 1);
  857. //    r.bottom -= (SBarSize - 1);
  858.  
  859.     if (r.right - r.left > dWin->bitMap.bounds.right - dWin->bitMap.bounds.left ||
  860.         r.bottom - r.top > dWin->bitMap.bounds.bottom - dWin->bitMap.bounds.top)
  861.         DebugStr("\pOy!");
  862.  
  863.     EraseRect(&r);
  864.  
  865.     DrawHeader(dWin, &r);
  866.  
  867.     r.top += (HeaderHeight+TopMargin+LineHeight-DescendHeight);
  868.     r.bottom -= (SBarSize+DescendHeight+BotMargin);
  869.  
  870.     DrawDump(dWin, &r, dWin->editOffset, dWin->fileSize);
  871.  
  872.     SetPortBits(&realBits);
  873.     SetPort(savePort);
  874.  
  875. #if PROFILE
  876.     _profile = 0;
  877. #endif
  878. }
  879.  
  880. void InvertSelection(EditWindowPtr    dWin)
  881. {
  882.     Rect    r;
  883. //LR    long    x;
  884.     long    start,end;
  885.     short    startX,endX;
  886.     Boolean    frontFlag;
  887.     unsigned char    HiliteMode = LMGetHiliteMode();    //LR :universal headers friendly
  888.  
  889.     frontFlag = ((WindowPtr) dWin == FrontWindow() &&
  890.                  dWin->oWin.active);
  891.  
  892.     if (dWin->endSel <= dWin->startSel)
  893.         return;
  894.  
  895.     start = dWin->startSel - dWin->editOffset;
  896.     if (start < 0)
  897.         start = 0;
  898.     end = (dWin->endSel-1) - dWin->editOffset;
  899.     if (end > (dWin->linesPerPage<<4)-1)
  900.         end = (dWin->linesPerPage<<4)-1;
  901.  
  902.     PenMode(patXor);
  903.     
  904.     startX = ColNbr(start);
  905.     endX = ColNbr(end);
  906.  
  907.     if (!frontFlag) {
  908.         if (LineNbr(start) < LineNbr(end)) {
  909.             // Invert Hex
  910.             r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  911.             r.bottom = r.top+LineHeight;
  912.             r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  913.             r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  914.  
  915.             MoveTo(AddrPos+CharPos(HexStart)-3,r.bottom);
  916.  
  917.             if (gColorQDFlag)
  918.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  919.             LineTo(r.left,r.bottom);
  920.             if (gColorQDFlag)
  921.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  922.             LineTo(r.left,r.top);
  923.             if (dWin->startSel >= dWin->editOffset) {
  924.                 if (gColorQDFlag)
  925.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  926.                 LineTo(r.right,r.top);
  927.             }
  928.             else
  929.                 MoveTo(r.right,r.top);
  930.             if (gColorQDFlag)
  931.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  932.             LineTo(r.right,r.bottom);
  933.  
  934.             // Outline Box around Ascii
  935.             r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  936.             r.right = AddrPos+CharPos(AsciiStart)+CharPos(16);
  937.             
  938.             MoveTo(AddrPos+CharPos(AsciiStart),r.bottom);
  939.             if (gColorQDFlag)
  940.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  941.             LineTo(r.left,r.bottom);
  942.  
  943.             if (gColorQDFlag)
  944.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  945.             LineTo(r.left,r.top);
  946.             if (dWin->startSel >= dWin->editOffset) {
  947.                 if (gColorQDFlag)
  948.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  949.                 LineTo(r.right,r.top);
  950.             }
  951.             else
  952.                 MoveTo(r.right,r.top);
  953.             if (gColorQDFlag)
  954.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  955.             LineTo(r.right,r.bottom);
  956.  
  957.             if (LineNbr(start) < LineNbr(end)-1) {
  958.                 r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight+LineHeight;
  959.                 r.bottom = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  960.                 r.left = AddrPos+CharPos(HexStart)-3;
  961.                 r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  962.                 MoveTo(r.left,r.top);
  963.                 if (gColorQDFlag)
  964.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  965.                 LineTo(r.left,r.bottom);
  966.                 MoveTo(r.right,r.top);
  967.                 if (gColorQDFlag)
  968.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  969.                 LineTo(r.right,r.bottom);
  970.  
  971.                 r.left = AddrPos+CharPos(AsciiStart)-1;
  972.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(16);
  973.                 MoveTo(r.left,r.top);
  974.                 if (gColorQDFlag)
  975.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  976.                 LineTo(r.left,r.bottom);
  977.                 MoveTo(r.right,r.top);
  978.                 if (gColorQDFlag)
  979.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  980.                 LineTo(r.right,r.bottom);
  981.             }
  982.             r.top = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  983.             r.bottom = r.top+LineHeight;
  984.             r.left = AddrPos+CharPos(HexStart)-3;
  985.             r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  986.             MoveTo(r.left,r.top);
  987.             if (gColorQDFlag)
  988.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  989.             LineTo(r.left,r.bottom);
  990.             if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  991.                 if (gColorQDFlag)
  992.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  993.                 LineTo(r.right,r.bottom);
  994.             }
  995.             else
  996.                 MoveTo(r.right,r.bottom);
  997.             if (gColorQDFlag)
  998.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  999.             LineTo(r.right,r.top);
  1000.             if (gColorQDFlag)
  1001.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1002.             LineTo(AddrPos+CharPos(HexStart)+HexPos(16)-3,r.top);
  1003.  
  1004.             r.left = AddrPos+CharPos(AsciiStart)-1;
  1005.             r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1006.             MoveTo(r.left,r.top);
  1007.             if (gColorQDFlag)
  1008.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1009.             LineTo(r.left,r.bottom-1);
  1010.             if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1011.                 if (gColorQDFlag)
  1012.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1013.                 LineTo(r.right,r.bottom-1);
  1014.             }
  1015.             else
  1016.                 MoveTo(r.right,r.bottom-1);
  1017.             if (gColorQDFlag)
  1018.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1019.             LineTo(r.right,r.top);
  1020.             if (gColorQDFlag)
  1021.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1022.             LineTo(AddrPos+CharPos(AsciiStart)+CharPos(16),r.top);
  1023.         }
  1024.         else {
  1025.             r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1026.             r.bottom = r.top+LineHeight;
  1027.             r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  1028.             r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  1029.             MoveTo(r.left,r.top);
  1030.             if (gColorQDFlag)
  1031.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1032.             LineTo(r.left,r.bottom);
  1033.             if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1034.                 if (gColorQDFlag)
  1035.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1036.                 LineTo(r.right,r.bottom);
  1037.             }
  1038.             else
  1039.                 MoveTo(r.right,r.bottom);
  1040.             if (gColorQDFlag)
  1041.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1042.             LineTo(r.right,r.top);
  1043.             if (dWin->startSel >= dWin->editOffset) {
  1044.                 if (gColorQDFlag)
  1045.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1046.                 LineTo(r.left,r.top);
  1047.             }
  1048.  
  1049.             r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  1050.             r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1051.  
  1052.             MoveTo(r.left,r.top);
  1053.             if (gColorQDFlag)
  1054.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1055.             LineTo(r.left,r.bottom-1);
  1056.             if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1057.                 if (gColorQDFlag)
  1058.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1059.                 LineTo(r.right,r.bottom-1);
  1060.             }
  1061.             else
  1062.                 MoveTo(r.right,r.bottom-1);
  1063.             if (gColorQDFlag)
  1064.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1065.             LineTo(r.right,r.top);
  1066.             if (dWin->startSel >= dWin->editOffset) {
  1067.                 if (gColorQDFlag)
  1068.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1069.                 LineTo(r.left,r.top);
  1070.             }
  1071.         }
  1072.     }
  1073.     else {
  1074.         if (dWin->editMode == EM_Hex) {
  1075.             if (LineNbr(start) < LineNbr(end)) {
  1076.     
  1077.                 // Invert Hex
  1078.                 r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1079.                 r.bottom = r.top+LineHeight;
  1080.                 r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  1081.                 r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  1082.     
  1083.                 if (gColorQDFlag)
  1084.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1085.                 InvertRect(&r);
  1086.     
  1087.     
  1088.                 // Outline Box around Ascii
  1089.                 r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  1090.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(16);
  1091.                 
  1092.                 MoveTo(AddrPos+CharPos(AsciiStart),r.bottom);
  1093.                 if (gColorQDFlag)
  1094.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1095.                 LineTo(r.left,r.bottom);
  1096.     
  1097.                 if (gColorQDFlag)
  1098.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1099.                 LineTo(r.left,r.top);
  1100.                 if (dWin->startSel >= dWin->editOffset) {
  1101.                     if (gColorQDFlag)
  1102.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1103.                     LineTo(r.right,r.top);
  1104.                 }
  1105.                 else
  1106.                     MoveTo(r.right,r.top);
  1107.                 if (gColorQDFlag)
  1108.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1109.                 LineTo(r.right,r.bottom);
  1110.     
  1111.                 if (LineNbr(start) < LineNbr(end)-1) {
  1112.                     r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight+LineHeight;
  1113.                     r.bottom = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  1114.                     r.left = AddrPos+CharPos(HexStart)-3;
  1115.                     r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  1116.                     if (gColorQDFlag)
  1117.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1118.                     InvertRect(&r);
  1119.     
  1120.                     r.left = AddrPos+CharPos(AsciiStart)-1;
  1121.                     r.right = AddrPos+CharPos(AsciiStart)+CharPos(16);
  1122.                     MoveTo(r.left,r.top);
  1123.                     if (gColorQDFlag)
  1124.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1125.                     LineTo(r.left,r.bottom);
  1126.                     MoveTo(r.right,r.top);
  1127.                     if (gColorQDFlag)
  1128.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1129.                     LineTo(r.right,r.bottom);
  1130.                 }
  1131.                 r.top = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  1132.                 r.bottom = r.top+LineHeight;
  1133.                 r.left = AddrPos+CharPos(HexStart)-3;
  1134.                 r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  1135.                 if (gColorQDFlag)
  1136.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1137.                 InvertRect(&r);
  1138.     
  1139.                 r.left = AddrPos+CharPos(AsciiStart)-1;
  1140.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1141.                 MoveTo(r.left,r.top);
  1142.                 if (gColorQDFlag)
  1143.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1144.                 LineTo(r.left,r.bottom-1);
  1145.                 if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1146.                     if (gColorQDFlag)
  1147.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1148.                     LineTo(r.right,r.bottom-1);
  1149.                 }
  1150.                 else
  1151.                     MoveTo(r.right,r.bottom-1);
  1152.                 if (gColorQDFlag)
  1153.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1154.                 LineTo(r.right,r.top);
  1155.                 if (gColorQDFlag)
  1156.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1157.                 LineTo(AddrPos+CharPos(AsciiStart)+CharPos(16),r.top);
  1158.             }
  1159.             else {
  1160.                 r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1161.                 r.bottom = r.top+LineHeight;
  1162.                 r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  1163.                 r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  1164.                 if (gColorQDFlag)
  1165.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1166.                 InvertRect(&r);
  1167.     
  1168.                 r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  1169.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1170.     
  1171.                 MoveTo(r.left,r.top);
  1172.                 if (gColorQDFlag)
  1173.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1174.                 LineTo(r.left,r.bottom-1);
  1175.                 if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1176.                     if (gColorQDFlag)
  1177.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1178.                     LineTo(r.right,r.bottom-1);
  1179.                 }
  1180.                 else
  1181.                     MoveTo(r.right,r.bottom-1);
  1182.                 if (gColorQDFlag)
  1183.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1184.                 LineTo(r.right,r.top);
  1185.                 if (dWin->startSel >= dWin->editOffset) {
  1186.                     if (gColorQDFlag)
  1187.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1188.                     LineTo(r.left,r.top);
  1189.                 }
  1190.             }
  1191.         }
  1192.         else {
  1193.             // Ascii Mode!!
  1194.             //
  1195.             if (LineNbr(start) < LineNbr(end)) {
  1196.     
  1197.                 // Invert Hex
  1198.                 r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1199.                 r.bottom = r.top+LineHeight;
  1200.                 r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  1201.                 r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  1202.     
  1203.                 MoveTo(AddrPos+CharPos(HexStart)-3,r.bottom);
  1204.                 if (gColorQDFlag)
  1205.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1206.                 LineTo(r.left,r.bottom);
  1207.                 if (gColorQDFlag)
  1208.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1209.                 LineTo(r.left,r.top);
  1210.                 if (dWin->startSel >= dWin->editOffset) {
  1211.                     if (gColorQDFlag)
  1212.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1213.                     LineTo(r.right,r.top);
  1214.                 }
  1215.                 else
  1216.                     MoveTo(r.right,r.top);
  1217.                 if (gColorQDFlag)
  1218.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1219.                 LineTo(r.right,r.bottom);
  1220.     
  1221.                 // Outline Box around Ascii
  1222.                 r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  1223.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(16)-1;
  1224.                 
  1225.                 if (gColorQDFlag)
  1226.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1227.                 InvertRect(&r);
  1228.     
  1229.                 if (LineNbr(start) < LineNbr(end)-1) {
  1230.                     r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight+LineHeight;
  1231.                     r.bottom = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  1232.                     r.left = AddrPos+CharPos(HexStart)-3;
  1233.                     r.right = AddrPos+CharPos(HexStart)+HexPos(16)-3;
  1234.                     MoveTo(r.left,r.top);
  1235.                     if (gColorQDFlag)
  1236.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1237.                     LineTo(r.left,r.bottom);
  1238.                     MoveTo(r.right,r.top);
  1239.                     if (gColorQDFlag)
  1240.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1241.                     LineTo(r.right,r.bottom);
  1242.     
  1243.                     r.left = AddrPos+CharPos(AsciiStart)-1;
  1244.                     r.right = AddrPos+CharPos(AsciiStart)+CharPos(16)-1;
  1245.                     if (gColorQDFlag)
  1246.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1247.                     InvertRect(&r);
  1248.                 }
  1249.                 r.top = HeaderHeight+TopMargin+LineNbr(end)*LineHeight;
  1250.                 r.bottom = r.top+LineHeight;
  1251.                 r.left = AddrPos+CharPos(HexStart)-3;
  1252.                 r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  1253.                 MoveTo(r.left,r.top);
  1254.                 if (gColorQDFlag)
  1255.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1256.                 LineTo(r.left,r.bottom);
  1257.                 if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1258.                     if (gColorQDFlag)
  1259.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1260.                     LineTo(r.right,r.bottom);
  1261.                 }
  1262.                 else
  1263.                     MoveTo(r.right,r.bottom);
  1264.                 if (gColorQDFlag)
  1265.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1266.                 LineTo(r.right,r.top);
  1267.                 if (gColorQDFlag)
  1268.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1269.                 LineTo(AddrPos+CharPos(HexStart)+HexPos(16)-3,r.top);
  1270.     
  1271.                 r.left = AddrPos+CharPos(AsciiStart)-1;
  1272.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1273.                 if (gColorQDFlag)
  1274.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1275.                 InvertRect(&r);
  1276.             }
  1277.             else {
  1278.                 r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1279.                 r.bottom = r.top+LineHeight;
  1280.                 r.left = AddrPos+CharPos(HexStart)+HexPos(startX)-3;
  1281.                 r.right = AddrPos+CharPos(HexStart)+HexPos(endX)+HexWidth-3;
  1282.                 MoveTo(r.left,r.top);
  1283.                 if (gColorQDFlag)
  1284.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1285.                 LineTo(r.left,r.bottom);
  1286.                 if (dWin->endSel < dWin->editOffset+dWin->linesPerPage*16) {
  1287.                     if (gColorQDFlag)
  1288.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1289.                     LineTo(r.right,r.bottom);
  1290.                 }
  1291.                 else
  1292.                     MoveTo(r.right,r.bottom);
  1293.                 if (gColorQDFlag)
  1294.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1295.                 LineTo(r.right,r.top);
  1296.                 if (dWin->startSel >= dWin->editOffset) {
  1297.                     if (gColorQDFlag)
  1298.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1299.                     LineTo(r.left,r.top);
  1300.                 }
  1301.     
  1302.                 r.left = AddrPos+CharPos(AsciiStart)+CharPos(startX)-1;
  1303.                 r.right = AddrPos+CharPos(AsciiStart)+CharPos(endX)+CharWidth-1;
  1304.                 if (gColorQDFlag)
  1305.                 HiliteMode &= ~(1 << hiliteBit);    // Hilite using Hilite Color
  1306.                 InvertRect(&r);
  1307.             }
  1308.         }
  1309.     }
  1310.     PenMode(patCopy);
  1311. }
  1312.  
  1313. void PrintWindow(EditWindowPtr dWin)
  1314. {
  1315.     TPPrPort    printPort;
  1316.     TPrStatus    prStatus;
  1317.     GrafPtr        savePort;
  1318.     Boolean        ok;
  1319.     Rect        r;
  1320.     short        pageNbr,startPage,endPage,nbrPages;
  1321.     long        startAddr,endAddr,addr;
  1322.     short        linesPerPage;
  1323.  
  1324.     GetPort(&savePort);
  1325.     PrOpen();
  1326.  
  1327.     ok = PrValidate(gHPrint);
  1328.     ok = PrJobDialog(gHPrint);
  1329.     if (ok) {
  1330.         if (dWin->startSel == dWin->endSel) {
  1331.             startAddr = 0;
  1332.             endAddr = dWin->fileSize;
  1333.         }
  1334.         else {
  1335.             startAddr = dWin->startSel;
  1336.             endAddr = dWin->endSel;
  1337.         }
  1338.  
  1339.         printPort = PrOpenDoc(gHPrint,NULL,NULL);
  1340.  
  1341.         r = printPort->gPort.portRect;
  1342.         linesPerPage = ((r.bottom - FooterHeight) - TopMargin - BotMargin - HeaderHeight)/LineHeight;
  1343.         nbrPages = ((endAddr - startAddr)/16)/linesPerPage + 1;
  1344.  
  1345.         startPage = (**gHPrint).prJob.iFstPage;
  1346.         endPage = (**gHPrint).prJob.iLstPage;
  1347.         if (startPage > nbrPages) {
  1348.             PrCloseDoc(printPort);
  1349.             ErrorAlert(ES_Caution, "Selected pages are out of range 1-%d",nbrPages);
  1350.             goto ErrorExit;
  1351.         }
  1352.         addr = startAddr;
  1353.  
  1354.         if (endPage > nbrPages)
  1355.             endPage = nbrPages;
  1356.  
  1357.         for (pageNbr = 1; pageNbr <= nbrPages; ++pageNbr) {
  1358.             SetPort(&printPort->gPort);
  1359.             PrOpenPage(printPort, NULL);
  1360.     
  1361.             if (pageNbr >= startPage && pageNbr <= endPage) {
  1362.                 r = printPort->gPort.portRect;
  1363.                 DrawHeader(dWin, &r);
  1364.         
  1365.                 r.top += (HeaderHeight+TopMargin+LineHeight-DescendHeight);
  1366.                 r.bottom -= (FooterHeight + DescendHeight + BotMargin);
  1367.         
  1368.                 DrawDump(dWin, &r, addr, endAddr);
  1369.     
  1370.                 r.top = r.bottom + DescendHeight + BotMargin;
  1371.                 r.bottom = r.top + FooterHeight;
  1372.                 DrawFooter(dWin, &r, pageNbr, nbrPages);
  1373.             }
  1374.  
  1375.             addr += linesPerPage*16;
  1376.             addr -= (addr % 16);
  1377.             PrClosePage(printPort);
  1378.         }
  1379.         PrCloseDoc(printPort);
  1380.         if ((**gHPrint).prJob.bJDocLoop == bSpoolLoop && PrError() == noErr)
  1381.             PrPicFile(gHPrint, NULL, NULL, NULL, &prStatus);
  1382.     }
  1383. ErrorExit:
  1384.     PrClose();
  1385.     SetPort(savePort);
  1386. }
  1387.  
  1388. void ScrollToSelection(EditWindowPtr dWin, long pos, Boolean forceUpdate, Boolean centerFlag)
  1389. {
  1390.     long    curAddr;
  1391.     curAddr = dWin->editOffset;
  1392.     if (pos >= curAddr && pos < curAddr+(dWin->linesPerPage<<4)) {
  1393.         if (forceUpdate) {
  1394.             DrawPage(dWin);
  1395.             UpdateOnscreen((WindowPtr) dWin);
  1396.         }
  1397.         AdjustScrollBars((WindowPtr) dWin,false);
  1398.         return;
  1399.     }
  1400.     if (centerFlag) {
  1401.         curAddr = pos - (pos % 16);
  1402.         curAddr -= 16 * (dWin->linesPerPage/2 - 1);
  1403.         // No need to adjust for limits, will be done by scroll routine
  1404.     }
  1405.     else {
  1406.  
  1407.         if (pos < curAddr) {
  1408.             // Scroll Up
  1409.             curAddr = pos;
  1410.             curAddr -= (curAddr % 16);
  1411.         }
  1412.         else {
  1413.             // Scroll Down
  1414.             curAddr = pos - (dWin->linesPerPage-1)*16;
  1415.             curAddr -= (curAddr % 16);
  1416.         }
  1417.     }
  1418.     HEditScrollToPosition(dWin, curAddr);
  1419. }
  1420.  
  1421. static void OffsetSelection(EditWindowPtr dWin, short offset, Boolean shiftFlag)
  1422. {
  1423.     long    selWidth;
  1424.     Boolean    fullUpdate;
  1425.     selWidth = dWin->endSel - dWin->startSel;
  1426.     fullUpdate = shiftFlag || selWidth > 1;
  1427.     if (offset < 0) {
  1428.         if (dWin->startSel > 0) {
  1429.             dWin->startSel += offset;
  1430.             if (dWin->startSel < 0)
  1431.                 dWin->startSel = 0;
  1432.             if (!shiftFlag) {
  1433.                 dWin->endSel = dWin->startSel;
  1434.                 CursorOff((WindowPtr) dWin);
  1435.             }
  1436.             ScrollToSelection(dWin, dWin->startSel, fullUpdate, false);
  1437.             if (!shiftFlag)
  1438.                 CursorOn((WindowPtr) dWin);
  1439.         }
  1440.         else
  1441.             SysBeep(1);
  1442.     }
  1443.     else {
  1444.         if (dWin->endSel < dWin->fileSize) {
  1445.             dWin->endSel += offset;
  1446.             if (dWin->endSel > dWin->fileSize)
  1447.                 dWin->endSel = dWin->fileSize;
  1448.             if (!shiftFlag) {
  1449.                 dWin->startSel = dWin->endSel;
  1450.                 CursorOff((WindowPtr) dWin);
  1451.             }
  1452.             ScrollToSelection(dWin, dWin->endSel, fullUpdate, false);
  1453.             if (!shiftFlag)
  1454.                 CursorOn((WindowPtr) dWin);
  1455.         }
  1456.         else
  1457.             SysBeep(1);
  1458.     }
  1459. }
  1460.  
  1461. void MyProcessKey(WindowPtr theWin, EventRecord *er)
  1462. {
  1463.     short    charCode,keyCode;
  1464.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  1465.  
  1466.     keyCode = (er->message & keyCodeMask) >> 8;
  1467.     charCode = (er->message & charCodeMask);
  1468.  
  1469.     if (er->modifiers & cmdKey)
  1470.         return;
  1471.  
  1472.     switch (keyCode) {
  1473.     case  0x24:            // Return
  1474.         break;
  1475.     case  0x7B:            // Left
  1476.         OffsetSelection(dWin, -1, (er->modifiers & shiftKey)>0);
  1477.         break;
  1478.     case 0x7C:            // Right
  1479.         OffsetSelection(dWin, 1, (er->modifiers & shiftKey)>0);
  1480.         break;
  1481.     case 0x7E:            // Up
  1482.         OffsetSelection(dWin, -16, (er->modifiers & shiftKey)>0);
  1483.         break;
  1484.     case 0x7D:            // Down
  1485.         OffsetSelection(dWin, 16, (er->modifiers & shiftKey)>0);
  1486.         break;
  1487.     case 0x33:            // Delete
  1488.         if (dWin->endSel > dWin->startSel) {
  1489.             ClearSelection(dWin);
  1490.         }
  1491.         else if (dWin->startSel > 0L) {
  1492.             ObscureCursor();
  1493.             --dWin->startSel;
  1494.             ClearSelection(dWin);
  1495.         }
  1496.         else
  1497.             SysBeep(1);
  1498.         break;
  1499.     default:
  1500.         // Insert Ascii Text Into Area indicated by dWin->startSel - dWin->endSel
  1501.         // Delete Current Selection if > 0
  1502.         ObscureCursor();
  1503.  
  1504.         if (dWin->editMode == EM_Ascii) {
  1505.             if (dWin->endSel != dWin->lastTypePos ||
  1506.                 dWin->startSel != dWin->lastTypePos)
  1507.                 RememberOperation(dWin, EO_Typing, &gUndoRec);
  1508.             if (dWin->endSel > dWin->startSel)
  1509.                 DeleteSelection(dWin);
  1510.             if (gOverwrite && dWin->startSel < dWin->fileSize - 1) {
  1511.                 ++dWin->endSel;
  1512.                 DeleteSelection(dWin);
  1513.             }
  1514.             InsertCharacter(dWin, charCode);
  1515.             dWin->lastTypePos = dWin->startSel;
  1516.         }
  1517.         else {
  1518.             short    hexVal;
  1519.  
  1520.             if (charCode >= '0' && charCode <= '9')
  1521.                 hexVal = charCode - '0';
  1522.             else if (charCode >= 'A' && charCode <= 'F')
  1523.                 hexVal = 0x0A + charCode - 'A';
  1524.             else if (charCode >= 'a' && charCode <= 'f')
  1525.                 hexVal = 0x0A + charCode - 'a';
  1526.             else {
  1527.                 SysBeep(1);
  1528.                 return;
  1529.             }
  1530.  
  1531.             if (dWin->endSel != dWin->lastTypePos ||
  1532.                 dWin->startSel != dWin->lastTypePos) {
  1533.                 dWin->loByteFlag = false;
  1534.                 RememberOperation(dWin, EO_Typing, &gUndoRec);
  1535.             }
  1536.             if (dWin->endSel > dWin->startSel)
  1537.                 DeleteSelection(dWin);
  1538.  
  1539.             if (dWin->loByteFlag) {
  1540.                 --dWin->startSel;
  1541.                 DeleteSelection(dWin);
  1542.                 hexVal = hexVal | (dWin->lastNybble << 4);
  1543.                 InsertCharacter(dWin, hexVal);
  1544.                 dWin->loByteFlag = false;
  1545.             }
  1546.             else {
  1547.                 if (gOverwrite && dWin->startSel < dWin->fileSize - 1) {
  1548.                     ++dWin->endSel;
  1549.                     DeleteSelection(dWin);
  1550.                 }
  1551.                 InsertCharacter(dWin, hexVal);
  1552.                 dWin->lastNybble = hexVal;
  1553.                 dWin->loByteFlag = true;
  1554.             }
  1555.             dWin->lastTypePos = dWin->startSel;
  1556.         }
  1557.         break;
  1558.     }
  1559. }
  1560.  
  1561. void CursorOff(WindowPtr theWin)
  1562. {
  1563.     if (gCursorFlag) {
  1564.         gCursorFlag = false;
  1565.         SetPort(theWin);
  1566.         InvertRect(&gCursRect);
  1567.     }
  1568. }
  1569.  
  1570. void CursorOn(WindowPtr theWin)
  1571. {
  1572.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  1573.     long            start;
  1574.     Rect            r;
  1575.  
  1576.     if (!gCursorFlag &&
  1577.          dWin->startSel >= dWin->editOffset &&
  1578.         dWin->startSel < dWin->editOffset+(dWin->linesPerPage<<4)) 
  1579.     {
  1580.         gCursorFlag = true;
  1581.         SetPort(theWin);
  1582.         start = dWin->startSel - dWin->editOffset;
  1583.  
  1584.         if (dWin->editMode == EM_Hex) {
  1585.             r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1586.             r.bottom = r.top+LineHeight;
  1587.             r.left = AddrPos+CharPos(HexStart)+ColNbr(start)*HexWidth-3;
  1588.             r.right = r.left+2;
  1589.             InvertRect(&r);
  1590.             gCursRect = r;
  1591.         }
  1592.         else {
  1593.             r.top = HeaderHeight+TopMargin+LineNbr(start)*LineHeight;
  1594.             r.bottom = r.top+LineHeight;
  1595.             r.left = AddrPos+CharPos(AsciiStart)+ColNbr(start)*CharWidth-2;
  1596.             r.right = r.left+2;
  1597.             InvertRect(&r);
  1598.             gCursRect = r;
  1599.         }
  1600.     }
  1601. }
  1602.  
  1603. static OSErr CopyFork(FSSpec *srcSpec, FSSpec *dstSpec, short forkType)
  1604. {
  1605.     short    sRefNum, dRefNum;
  1606.     OSErr    oe;
  1607.     Ptr        tBuffer;
  1608.     long    srcSize=0L,bufSize,count;
  1609.  
  1610.     tBuffer = NewPtr(32000);
  1611.  
  1612.     if (tBuffer == NULL) {
  1613.         ErrorAlert(ES_Caution, "Not Enough Memory");
  1614.         return 1;
  1615.     }
  1616.     if (forkType == FT_Resource) {
  1617.         oe = HOpenRF(srcSpec->vRefNum,srcSpec->parID,srcSpec->name,fsRdPerm,&sRefNum);
  1618.         if (oe != noErr) {
  1619.             OSErrorAlert(ES_Caution, "HOpenRF", oe);
  1620.             return oe;
  1621.         }
  1622.         oe = HOpenRF(dstSpec->vRefNum,dstSpec->parID,dstSpec->name,fsWrPerm,&dRefNum);
  1623.         if (oe != noErr) {
  1624.             OSErrorAlert(ES_Caution, "HOpenRF", oe);
  1625.             return oe;
  1626.         }
  1627.     }
  1628.     else {
  1629.         oe = HOpen(srcSpec->vRefNum,srcSpec->parID,srcSpec->name,fsRdPerm,&sRefNum);
  1630.         if (oe != noErr) {
  1631.             OSErrorAlert(ES_Caution, "HOpen", oe);
  1632.             return oe;
  1633.         }
  1634.         oe = HOpen(dstSpec->vRefNum,dstSpec->parID,dstSpec->name,fsWrPerm,&dRefNum);
  1635.         if (oe != noErr) {
  1636.             OSErrorAlert(ES_Caution, "HOpen", oe);
  1637.             return oe;
  1638.         }
  1639.     }
  1640.     GetEOF(sRefNum, &srcSize);
  1641.     SetEOF(dRefNum,0L);
  1642.     while (srcSize) {
  1643.         if (srcSize < 32000)
  1644.             bufSize = srcSize;
  1645.         else
  1646.             bufSize = 32000;
  1647.         srcSize -= bufSize;
  1648.         count = bufSize;
  1649.         oe = FSRead(sRefNum, &count, tBuffer);
  1650.         if (oe != noErr) {
  1651.             OSErrorAlert(ES_Caution,"FSRead",oe);
  1652.             goto ErrorExit;
  1653.         }
  1654.         oe = FSWrite(dRefNum, &count, tBuffer);
  1655.         if (oe != noErr) {
  1656.             OSErrorAlert(ES_Caution,"FSWrite",oe);
  1657.             goto ErrorExit;
  1658.         }
  1659.     }
  1660.     oe = noErr;
  1661. ErrorExit:
  1662.     FSClose(sRefNum);
  1663.     FSClose(dRefNum);
  1664.     DisposePtr(tBuffer);
  1665.     return oe;
  1666. }
  1667.  
  1668. void InsureNameIsUnique(FSSpec *tSpec)
  1669. {
  1670.     FInfo            fInfo;
  1671.     while (HGetFInfo(tSpec->vRefNum,
  1672.                      tSpec->parID,
  1673.                      tSpec->name, &fInfo) == noErr) {
  1674.         tSpec->name[1+MyRandom(tSpec->name[0])] = 0x80+MyRandom(64);
  1675.     }
  1676. }
  1677.  
  1678. void SaveContents(WindowPtr theWin)
  1679. {
  1680.     short            tRefNum=0;
  1681.     FSSpec            tSpec,bSpec;
  1682.     HParamBlockRec    pb;
  1683.     EditChunk        **cc;
  1684.     EditWindowPtr    dWin;
  1685.     long            count;
  1686.     OSErr            oe;
  1687.  
  1688.     dWin = (EditWindowPtr) theWin;
  1689.     if (dWin->destSpec.name[0] == 0) {
  1690.         SaveAsContents(theWin);
  1691.     }
  1692.     else {
  1693.         // Create temp file
  1694.         tSpec = dWin->destSpec;
  1695.  
  1696.         // If original file exists, write to temp folder
  1697.         if (dWin->refNum) {
  1698.             if (tSpec.name[0] < 31) {
  1699.                 tSpec.name[0]++;
  1700.                 tSpec.name[tSpec.name[0]] = 't';
  1701.             }
  1702.             else {
  1703.                 tSpec.name[31] ^= 0x10;
  1704.             }
  1705.         }
  1706.         InsureNameIsUnique(&tSpec);
  1707.  
  1708.         HDelete(tSpec.vRefNum,tSpec.parID,tSpec.name);
  1709.         oe = HCreate(tSpec.vRefNum,tSpec.parID,tSpec.name,dWin->creator, dWin->fileType);
  1710.         if (oe != noErr) {
  1711.             OSErrorAlert(ES_Caution, "HCreate", oe);
  1712.             return;
  1713.         }
  1714.  
  1715.         // Preserve creation date of orig file if it exists
  1716.         if (dWin->creationDate) {
  1717.             pb.fileParam.ioCompletion = 0l;
  1718.             pb.fileParam.ioNamePtr = tSpec.name;
  1719.             pb.fileParam.ioVRefNum = tSpec.vRefNum;
  1720.             pb.fileParam.ioDirID = tSpec.parID;
  1721.             pb.fileParam.ioFDirIndex = 0;
  1722.         
  1723.             if ((oe = PBHGetFInfoSync(&pb)) != noErr) {
  1724.                 OSErrorAlert(ES_Caution, "PBHGetFInfo", oe);
  1725.                 return;
  1726.             }
  1727.             // Reset dirID which PBHGeFInfo changes...
  1728.             pb.fileParam.ioFlCrDat = dWin->creationDate;
  1729.             pb.fileParam.ioDirID = tSpec.parID;
  1730.             if ((oe = PBHSetFInfoSync(&pb)) != noErr) {
  1731.                 OSErrorAlert(ES_Caution, "PBHSetFInfo", oe);
  1732.                 return;
  1733.             }
  1734.         }
  1735.         // Preserve other fork if it exists
  1736.         if (dWin->refNum)
  1737.             if (CopyFork(&dWin->fsSpec,&tSpec, !dWin->fork) != noErr)
  1738.                 return;
  1739.  
  1740.         // Open the temp file
  1741.         if (dWin->fork == FT_Resource) {
  1742.             oe = HOpenRF(tSpec.vRefNum,tSpec.parID,tSpec.name,fsWrPerm,&tRefNum);
  1743.             if (oe != noErr) {
  1744.                 OSErrorAlert(ES_Caution, "HOpenRF", oe);
  1745.                 return;
  1746.             }
  1747.         }
  1748.         else {
  1749.             oe = HOpen(tSpec.vRefNum,tSpec.parID,tSpec.name,fsWrPerm,&tRefNum);
  1750.             if (oe != noErr) {
  1751.                 OSErrorAlert(ES_Caution, "HOpen", oe);
  1752.                 return;
  1753.             }
  1754.         }
  1755.         
  1756.         // Save out to temp file
  1757.         cc = dWin->firstChunk;
  1758.         while (cc) {
  1759.             LoadChunk(dWin, cc);
  1760.             count = (*cc)->size;
  1761.             oe = FSWrite(tRefNum, &count, *(*cc)->data);
  1762.             if (oe != noErr) {
  1763.                 // !! Error Message - write error
  1764.                 FSClose(tRefNum);
  1765.                 if (oe == dskFulErr)
  1766.                     goto DiskFull;
  1767.                 OSErrorAlert(ES_Caution, "FSWrite", oe);
  1768.                 return;
  1769.             }
  1770.             cc = (*cc)->next;
  1771.         }
  1772.  
  1773.         // Close temp file
  1774.         FSClose(tRefNum);
  1775.  
  1776.         // If Original File Exists
  1777.         if (dWin->refNum) {
  1778.             // Close original file
  1779.             FSClose(dWin->refNum);
  1780.  
  1781.             bSpec = dWin->destSpec;
  1782.  
  1783.             // If it exists under current name
  1784.             if ((oe = HOpen(bSpec.vRefNum,bSpec.parID,bSpec.name,fsRdPerm,&dWin->refNum)) == noErr)
  1785.             {
  1786.                 FSClose(dWin->refNum);
  1787.  
  1788.                 if (gPrefs.backupFlag) {
  1789.                     // Delete last backup file, if it exists
  1790.                     bSpec = dWin->destSpec;
  1791.                     bSpec.name[0]++;
  1792.                     bSpec.name[bSpec.name[0]] = '~';
  1793.                     HDelete(bSpec.vRefNum,bSpec.parID,bSpec.name);
  1794.         
  1795.                     // Rename original file to backup name
  1796.                     oe = HRename(dWin->destSpec.vRefNum,
  1797.                                  dWin->destSpec.parID,
  1798.                                  dWin->destSpec.name,
  1799.                                   bSpec.name);
  1800.                     if (oe != noErr) {
  1801.                         // Backup is probably open, just delete original
  1802.                         ErrorAlert(ES_Caution, "Can't backup original - backup file is open", oe);
  1803.                         bSpec = dWin->destSpec;
  1804.                         HDelete(bSpec.vRefNum,bSpec.parID,bSpec.name);
  1805.                     }
  1806.                 }
  1807.                 else {
  1808.                     // Delete Original if backup flag is false
  1809.                     bSpec = dWin->destSpec;
  1810.                     HDelete(bSpec.vRefNum,bSpec.parID,bSpec.name);
  1811.                 }
  1812.             }
  1813.  
  1814.             // Rename temp file to correct name
  1815.             oe = HRename(tSpec.vRefNum,
  1816.                         tSpec.parID,
  1817.                         tSpec.name,
  1818.                         dWin->destSpec.name);
  1819.             if (oe != noErr) {
  1820.                 OSErrorAlert(ES_Stop, "HRename", oe);
  1821.             }
  1822.         }
  1823.  
  1824.         // Open newly saved file read only
  1825.         tSpec = dWin->destSpec;
  1826.         if (dWin->fork == FT_Resource) {
  1827.             oe = HOpenRF(tSpec.vRefNum,tSpec.parID,tSpec.name,fsRdPerm,&dWin->refNum);
  1828.             if (oe != noErr) {
  1829.                 OSErrorAlert(ES_Stop, "HOpenRF", oe);
  1830.             }
  1831.         }
  1832.         else {
  1833.             oe = HOpen(tSpec.vRefNum,tSpec.parID,tSpec.name,fsRdPerm,&dWin->refNum);
  1834.             if (oe != noErr) {
  1835.                 OSErrorAlert(ES_Stop, "HOpen", oe);
  1836.             }
  1837.         }
  1838.  
  1839.         // Reset Work File
  1840.         dWin->fsSpec = dWin->destSpec;
  1841.         SetWTitle((WindowPtr) dWin, dWin->fsSpec.name);
  1842.  
  1843.         dWin->workBytesWritten = 0L;
  1844.         SetEOF(dWin->workRefNum, 0L);
  1845.  
  1846.         // Flush the volume
  1847.         pb.volumeParam.ioCompletion = NULL;
  1848.         pb.volumeParam.ioNamePtr = NULL;
  1849.         pb.volumeParam.ioVRefNum = tSpec.vRefNum;
  1850.         PBFlushVolSync((ParmBlkPtr) &pb);
  1851.  
  1852.         // Clear linked list
  1853.         UnloadFile(dWin);
  1854.  
  1855.         // Rebuilt linked list
  1856.         LoadFile(dWin);
  1857.  
  1858.         // Clear Dirty Flag
  1859.         dWin->dirtyFlag = false;
  1860.     }
  1861.     return;
  1862. DiskFull:
  1863.     ErrorAlert(ES_Caution, "Can't save - the disk is full.  Try freeing some space or using another disk.");
  1864.     HDelete(tSpec.vRefNum,tSpec.parID,tSpec.name);
  1865. }
  1866.  
  1867. void SaveAsContents(WindowPtr theWin)
  1868. {
  1869.     StandardFileReply    reply;
  1870.     EditWindowPtr        dWin = (EditWindowPtr) theWin;
  1871.     Str63                fileName;
  1872.     GetWTitle(theWin, fileName);
  1873.     StandardPutFile("\pFile to save:", 
  1874.                     fileName, 
  1875.                     &reply);
  1876.     if (reply.sfGood) {
  1877.         dWin->destSpec = reply.sfFile;
  1878.         dWin->creationDate = 0;
  1879.         SaveContents(theWin);
  1880.     }
  1881. }
  1882.  
  1883. void RevertContents(WindowPtr theWin)
  1884. {
  1885.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  1886.     long            newEOF;
  1887.  
  1888.     // Reset Work File
  1889.     dWin->workBytesWritten = 0L;
  1890.     SetEOF(dWin->workRefNum, 0L);
  1891.  
  1892.     // Clear linked list
  1893.     UnloadFile(dWin);
  1894.  
  1895.     // Reset EOF
  1896.     GetEOF(dWin->refNum, &newEOF);
  1897.  
  1898.     dWin->fileSize = newEOF;
  1899.  
  1900.     // Rebuilt linked list
  1901.     LoadFile(dWin);
  1902.  
  1903.     // Reset scroll offset, if necessary
  1904.     if (dWin->editOffset > dWin->fileSize -16*dWin->linesPerPage)
  1905.         dWin->editOffset = 0;
  1906.     DrawPage(dWin);
  1907.     UpdateOnscreen(theWin);
  1908. }
  1909.  
  1910. void MyActivate(WindowPtr theWin, Boolean active)
  1911. {
  1912.     EditWindowPtr    dWin = (EditWindowPtr) theWin;
  1913.     if (dWin->vScrollBar)
  1914.         HiliteControl(dWin->vScrollBar,active? 0 : 255);
  1915.     DefaultActivate(theWin, active);
  1916. }
  1917.  
  1918. void UpdateEditWindows(void)
  1919. {
  1920.     WindowPeek    theWin;
  1921.     theWin = (WindowPeek) FrontWindow();
  1922.     while (theWin) {
  1923.         if (theWin->refCon == MyWindowID) {
  1924.             DrawPage((EditWindowPtr) theWin);
  1925.             UpdateOnscreen((WindowPtr) theWin);
  1926.         }
  1927.         theWin = theWin->nextWindow;
  1928.     }
  1929. }
  1930.  
  1931.